vulkan: Add GskVulkanUploader
authorBenjamin Otte <otte@redhat.com>
Sat, 17 Dec 2016 03:22:44 +0000 (04:22 +0100)
committerBenjamin Otte <otte@redhat.com>
Tue, 20 Dec 2016 17:01:11 +0000 (18:01 +0100)
It's the thing that makes sure pixels end up on the GPU.

gsk/gskvulkanimage.c
gsk/gskvulkanimageprivate.h
gsk/gskvulkanrender.c
gsk/gskvulkanrenderer.c
gsk/gskvulkanrendererprivate.h
gsk/gskvulkanrenderpass.c
gsk/gskvulkanrenderpassprivate.h

index f65b021fe4427b50a92d4bbf504a25eff5e96f04..e0550e73cbeb26d3f7ea4740c7755c202044da9c 100644 (file)
@@ -8,6 +8,16 @@
 
 #include <string.h>
 
+struct _GskVulkanUploader
+{
+  GdkVulkanContext *vulkan;
+
+  GskVulkanCommandPool *command_pool;
+
+  GSList *staging_image_free_list;
+  GSList *staging_buffer_free_list;
+};
+
 struct _GskVulkanImage
 {
   GObject parent_instance;
@@ -24,6 +34,39 @@ struct _GskVulkanImage
 
 G_DEFINE_TYPE (GskVulkanImage, gsk_vulkan_image, G_TYPE_OBJECT)
 
+GskVulkanUploader *
+gsk_vulkan_uploader_new (GdkVulkanContext     *context,
+                         GskVulkanCommandPool *command_pool)
+{
+  GskVulkanUploader *self;
+
+  self = g_slice_new0 (GskVulkanUploader);
+
+  self->vulkan = g_object_ref (context);
+  self->command_pool = command_pool;
+
+  return self;
+}
+
+void
+gsk_vulkan_uploader_free (GskVulkanUploader *self)
+{
+  gsk_vulkan_uploader_reset (self);
+
+  g_object_unref (self->vulkan);
+
+  g_slice_free (GskVulkanUploader, self);
+}
+
+void
+gsk_vulkan_uploader_reset (GskVulkanUploader *self)
+{
+  g_slist_free_full (self->staging_image_free_list, g_object_unref);
+  self->staging_image_free_list = NULL;
+  g_slist_free_full (self->staging_buffer_free_list, (GDestroyNotify) gsk_vulkan_buffer_free);
+  self->staging_buffer_free_list = NULL;
+}
+
 static GskVulkanImage *
 gsk_vulkan_image_new (GdkVulkanContext      *context,
                       gsize                  width,
@@ -139,19 +182,18 @@ gsk_vulkan_image_ensure_view (GskVulkanImage *self,
 }
 
 GskVulkanImage *
-gsk_vulkan_image_new_from_data_via_staging_buffer (GdkVulkanContext     *context,
-                                                   GskVulkanCommandPool *command_pool,
-                                                   guchar               *data,
-                                                   gsize                 width,
-                                                   gsize                 height,
-                                                   gsize                 stride)
+gsk_vulkan_image_new_from_data_via_staging_buffer (GskVulkanUploader *uploader,
+                                                   guchar            *data,
+                                                   gsize              width,
+                                                   gsize              height,
+                                                   gsize              stride)
 {
   GskVulkanImage *self;
   GskVulkanBuffer *staging;
   VkCommandBuffer command_buffer;
   guchar *mem;
 
-  staging = gsk_vulkan_buffer_new_staging (context, width * height * 4);
+  staging = gsk_vulkan_buffer_new_staging (uploader->vulkan, width * height * 4);
   mem = gsk_vulkan_buffer_map (staging);
 
   if (stride == width * 4)
@@ -168,14 +210,14 @@ gsk_vulkan_image_new_from_data_via_staging_buffer (GdkVulkanContext     *context
 
   gsk_vulkan_buffer_unmap (staging);
 
-  self = gsk_vulkan_image_new (context,
+  self = gsk_vulkan_image_new (uploader->vulkan,
                                width,
                                height, 
                                VK_IMAGE_TILING_OPTIMAL,
                                VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
                                VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
 
-  command_buffer = gsk_vulkan_command_pool_get_buffer (command_pool);
+  command_buffer = gsk_vulkan_command_pool_get_buffer (uploader->command_pool);
 
   vkCmdPipelineBarrier (command_buffer,
                         VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
@@ -252,10 +294,9 @@ gsk_vulkan_image_new_from_data_via_staging_buffer (GdkVulkanContext     *context
                             }
                         });
 
-  gsk_vulkan_command_pool_submit_buffer (command_pool, command_buffer, VK_NULL_HANDLE);
+  gsk_vulkan_command_pool_submit_buffer (uploader->command_pool, command_buffer, VK_NULL_HANDLE);
 
-  /* XXX: Is this okay or do we need to keep the staging image around until the commands execute */
-  gsk_vulkan_buffer_free (staging);
+  uploader->staging_buffer_free_list = g_slist_prepend (uploader->staging_buffer_free_list, staging);
 
   gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_SRGB);
 
@@ -263,17 +304,16 @@ gsk_vulkan_image_new_from_data_via_staging_buffer (GdkVulkanContext     *context
 }
 
 GskVulkanImage *
-gsk_vulkan_image_new_from_data_via_staging_image (GdkVulkanContext     *context,
-                                                  GskVulkanCommandPool *command_pool,
-                                                  guchar               *data,
-                                                  gsize                 width,
-                                                  gsize                 height,
-                                                  gsize                 stride)
+gsk_vulkan_image_new_from_data_via_staging_image (GskVulkanUploader *uploader,
+                                                  guchar            *data,
+                                                  gsize              width,
+                                                  gsize              height,
+                                                  gsize              stride)
 {
   GskVulkanImage *self, *staging;
   VkCommandBuffer command_buffer;
 
-  staging = gsk_vulkan_image_new (context,
+  staging = gsk_vulkan_image_new (uploader->vulkan,
                                   width,
                                   height, 
                                   VK_IMAGE_TILING_LINEAR,
@@ -282,14 +322,14 @@ gsk_vulkan_image_new_from_data_via_staging_image (GdkVulkanContext     *context,
 
   gsk_vulkan_image_upload_data (staging, data, width, height, stride);
 
-  self = gsk_vulkan_image_new (context,
+  self = gsk_vulkan_image_new (uploader->vulkan,
                                width,
                                height, 
                                VK_IMAGE_TILING_OPTIMAL,
                                VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
                                VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
 
-  command_buffer = gsk_vulkan_command_pool_get_buffer (command_pool);
+  command_buffer = gsk_vulkan_command_pool_get_buffer (uploader->command_pool);
 
   vkCmdPipelineBarrier (command_buffer,
                         VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
@@ -388,10 +428,9 @@ gsk_vulkan_image_new_from_data_via_staging_image (GdkVulkanContext     *context,
                             }
                         });
 
-  gsk_vulkan_command_pool_submit_buffer (command_pool, command_buffer, VK_NULL_HANDLE);
+  gsk_vulkan_command_pool_submit_buffer (uploader->command_pool, command_buffer, VK_NULL_HANDLE);
 
-  /* XXX: Is this okay or do we need to keep the staging image around until the commands execute */
-  g_object_unref (staging);
+  uploader->staging_image_free_list = g_slist_prepend (uploader->staging_image_free_list, staging);
 
   gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_SRGB);
 
@@ -399,19 +438,18 @@ gsk_vulkan_image_new_from_data_via_staging_image (GdkVulkanContext     *context,
 }
 
 GskVulkanImage *
-gsk_vulkan_image_new_from_data_directly (GdkVulkanContext     *context,
-                                         GskVulkanCommandPool *command_pool,
-                                         guchar               *data,
-                                         gsize                 width,
-                                         gsize                 height,
-                                         gsize                 stride)
+gsk_vulkan_image_new_from_data_directly (GskVulkanUploader *uploader,
+                                         guchar            *data,
+                                         gsize              width,
+                                         gsize              height,
+                                         gsize              stride)
 {
   VkCommandBuffer command_buffer;
   GskVulkanImage *self;
 
-  command_buffer = gsk_vulkan_command_pool_get_buffer (command_pool);
+  command_buffer = gsk_vulkan_command_pool_get_buffer (uploader->command_pool);
 
-  self = gsk_vulkan_image_new (context,
+  self = gsk_vulkan_image_new (uploader->vulkan,
                                width,
                                height, 
                                VK_IMAGE_TILING_LINEAR,
@@ -446,7 +484,7 @@ gsk_vulkan_image_new_from_data_directly (GdkVulkanContext     *context,
                             }
                         });
 
-  gsk_vulkan_command_pool_submit_buffer (command_pool, command_buffer, VK_NULL_HANDLE);
+  gsk_vulkan_command_pool_submit_buffer (uploader->command_pool, command_buffer, VK_NULL_HANDLE);
 
   gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_SRGB);
 
@@ -454,19 +492,18 @@ gsk_vulkan_image_new_from_data_directly (GdkVulkanContext     *context,
 }
 
 GskVulkanImage *
-gsk_vulkan_image_new_from_data (GdkVulkanContext     *context,
-                                GskVulkanCommandPool *command_pool,
-                                guchar               *data,
-                                gsize                 width,
-                                gsize                 height,
-                                gsize                 stride)
+gsk_vulkan_image_new_from_data (GskVulkanUploader *uploader,
+                                guchar            *data,
+                                gsize              width,
+                                gsize              height,
+                                gsize              stride)
 {
   if (GSK_RENDER_MODE_CHECK (STAGING_BUFFER))
-    return gsk_vulkan_image_new_from_data_via_staging_buffer (context, command_pool, data, width, height, stride);
+    return gsk_vulkan_image_new_from_data_via_staging_buffer (uploader, data, width, height, stride);
   if (GSK_RENDER_MODE_CHECK (STAGING_IMAGE))
-    return gsk_vulkan_image_new_from_data_via_staging_image (context, command_pool, data, width, height, stride);
+    return gsk_vulkan_image_new_from_data_via_staging_image (uploader, data, width, height, stride);
   else
-    return gsk_vulkan_image_new_from_data_directly (context, command_pool, data, width, height, stride);
+    return gsk_vulkan_image_new_from_data_directly (uploader, data, width, height, stride);
 }
 
 GskVulkanImage *
index 3d6668e34735c5f8c616c9d67ffc499093a4b58e..e146ce7cf6ffd0ecdafd54921acf4b4c1fb6bae3 100644 (file)
@@ -7,17 +7,24 @@
 
 G_BEGIN_DECLS
 
+typedef struct _GskVulkanUploader GskVulkanUploader;
+
 #define GSK_TYPE_VULKAN_IMAGE (gsk_vulkan_image_get_type ())
 
 G_DECLARE_FINAL_TYPE (GskVulkanImage, gsk_vulkan_image, GSK, VULKAN_IMAGE, GObject)
 
+GskVulkanUploader *     gsk_vulkan_uploader_new                         (GdkVulkanContext       *context,
+                                                                         GskVulkanCommandPool   *command_pool);
+void                    gsk_vulkan_uploader_free                        (GskVulkanUploader      *self);
+
+void                    gsk_vulkan_uploader_reset                       (GskVulkanUploader      *self);
+
 GskVulkanImage *        gsk_vulkan_image_new_for_swapchain              (GdkVulkanContext       *context,
                                                                          VkImage                 image,
                                                                          VkFormat                format,
                                                                          gsize                   width,
                                                                          gsize                   height);
-GskVulkanImage *        gsk_vulkan_image_new_from_data                  (GdkVulkanContext       *context,
-                                                                         GskVulkanCommandPool   *pool,
+GskVulkanImage *        gsk_vulkan_image_new_from_data                  (GskVulkanUploader      *uploader,
                                                                          guchar                 *data,
                                                                          gsize                   width,
                                                                          gsize                   height,
index dffd20d2562170e54729f16568719501e1f2fd53..4d0f5f715a5f25b2ec76b7dc4605f9c0ad86c594 100644 (file)
@@ -29,6 +29,7 @@ struct _GskVulkanRender
   VkFence fence;
   VkRenderPass render_pass;
   GskVulkanPipelineLayout *layout;
+  GskVulkanUploader *uploader;
 
   GHashTable *descriptor_set_indexes;
   VkDescriptorPool descriptor_pool;
@@ -155,6 +156,8 @@ gsk_vulkan_render_new (GskRenderer      *renderer,
 
   self->layout = gsk_vulkan_pipeline_layout_new (self->vulkan);
 
+  self->uploader = gsk_vulkan_uploader_new (self->vulkan, self->command_pool);
+
   return self;
 }
 
@@ -235,7 +238,7 @@ gsk_vulkan_render_upload (GskVulkanRender *self)
 
   for (l = self->render_passes; l; l = l->next)
     {
-      gsk_vulkan_render_pass_upload (l->data, self, self->command_pool);
+      gsk_vulkan_render_pass_upload (l->data, self, self->uploader);
     }
 }
 
@@ -515,6 +518,8 @@ gsk_vulkan_render_cleanup (GskVulkanRender *self)
                                1,
                                &self->fence);
 
+  gsk_vulkan_uploader_reset (self->uploader);
+
   gsk_vulkan_command_pool_reset (self->command_pool);
 
   g_hash_table_remove_all (self->descriptor_set_indexes);
@@ -556,6 +561,8 @@ gsk_vulkan_render_free (GskVulkanRender *self)
   for (i = 0; i < GSK_VULKAN_N_PIPELINES; i++)
     g_clear_object (&self->pipelines[i]);
 
+  g_clear_pointer (&self->uploader, gsk_vulkan_uploader_free);
+
   g_clear_pointer (&self->layout, gsk_vulkan_pipeline_layout_unref);
 
   vkDestroyRenderPass (device,
index cf550b3fea76136c3fc0becc76df1cae7fcc3230..3cab29fd4a43696baf1858a963a9f797044ec882 100644 (file)
@@ -269,9 +269,9 @@ gsk_vulkan_renderer_clear_texture (gpointer p)
 }
 
 GskVulkanImage *
-gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer    *self,
-                                       GskTexture           *texture,
-                                       GskVulkanCommandPool *command_pool)
+gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self,
+                                       GskTexture        *texture,
+                                       GskVulkanUploader *uploader)
 {
   GskVulkanTextureData *data;
   cairo_surface_t *surface;
@@ -282,8 +282,7 @@ gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer    *self,
     return g_object_ref (data->image);
 
   surface = gsk_texture_download (texture);
-  image = gsk_vulkan_image_new_from_data (self->vulkan,
-                                          command_pool,
+  image = gsk_vulkan_image_new_from_data (uploader,
                                           cairo_image_surface_get_data (surface),
                                           cairo_image_surface_get_width (surface),
                                           cairo_image_surface_get_height (surface),
index 982983a77772147c427c6c66ab0d3ac7d719da16..5794ba1d53cde42914e20624f276759943318dcd 100644 (file)
@@ -23,7 +23,7 @@ GType gsk_vulkan_renderer_get_type (void) G_GNUC_CONST;
 
 GskVulkanImage *        gsk_vulkan_renderer_ref_texture_image           (GskVulkanRenderer      *self,
                                                                          GskTexture             *texture,
-                                                                         GskVulkanCommandPool   *command_pool);
+                                                                         GskVulkanUploader      *uploader);
 
 G_END_DECLS
 
index 6e1461c5df8973777a3c8d2de9d1fb1743d0a22c..5290d0e6001825ea6ea095ffe3f1ec48333ad5a9 100644 (file)
@@ -176,7 +176,7 @@ static void
 gsk_vulkan_render_pass_upload_fallback (GskVulkanRenderPass  *self,
                                         GskVulkanOpRender    *op,
                                         GskVulkanRender      *render,
-                                        GskVulkanCommandPool *command_pool)
+                                        GskVulkanUploader    *uploader)
 {
   graphene_rect_t bounds;
   cairo_surface_t *surface;
@@ -194,8 +194,7 @@ gsk_vulkan_render_pass_upload_fallback (GskVulkanRenderPass  *self,
   
   cairo_destroy (cr);
 
-  op->source = gsk_vulkan_image_new_from_data (self->vulkan,
-                                               command_pool,
+  op->source = gsk_vulkan_image_new_from_data (uploader,
                                                cairo_image_surface_get_data (surface),
                                                cairo_image_surface_get_width (surface),
                                                cairo_image_surface_get_height (surface),
@@ -209,7 +208,7 @@ gsk_vulkan_render_pass_upload_fallback (GskVulkanRenderPass  *self,
 void
 gsk_vulkan_render_pass_upload (GskVulkanRenderPass  *self,
                                GskVulkanRender      *render,
-                               GskVulkanCommandPool *command_pool)
+                               GskVulkanUploader    *uploader)
 {
   GskVulkanOp *op;
   guint i;
@@ -221,14 +220,13 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass  *self,
       switch (op->type)
         {
         case GSK_VULKAN_OP_FALLBACK:
-          gsk_vulkan_render_pass_upload_fallback (self, &op->render, render, command_pool);
+          gsk_vulkan_render_pass_upload_fallback (self, &op->render, render, uploader);
           break;
 
         case GSK_VULKAN_OP_SURFACE:
           {
             cairo_surface_t *surface = gsk_cairo_node_get_surface (op->render.node);
-            op->render.source = gsk_vulkan_image_new_from_data (self->vulkan,
-                                                                command_pool,
+            op->render.source = gsk_vulkan_image_new_from_data (uploader,
                                                                 cairo_image_surface_get_data (surface),
                                                                 cairo_image_surface_get_width (surface),
                                                                 cairo_image_surface_get_height (surface),
@@ -241,7 +239,7 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass  *self,
           {
             op->render.source = gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)),
                                                                        gsk_texture_node_get_texture (op->render.node),
-                                                                       command_pool);
+                                                                       uploader);
             gsk_vulkan_render_add_cleanup_image (render, op->render.source);
           }
           break;
index 7d5478dabc33f66f4b4786fb78e19e0ef145e561..fa012798b06770906fdea460144988ffdf5a617e 100644 (file)
@@ -21,7 +21,7 @@ void                    gsk_vulkan_render_pass_add                      (GskVulk
 
 void                    gsk_vulkan_render_pass_upload                   (GskVulkanRenderPass    *self,
                                                                          GskVulkanRender        *render,
-                                                                         GskVulkanCommandPool   *command_pool);
+                                                                         GskVulkanUploader      *uploader);
 
 gsize                   gsk_vulkan_render_pass_count_vertices           (GskVulkanRenderPass    *self);
 gsize                   gsk_vulkan_render_pass_collect_vertices         (GskVulkanRenderPass    *self,